﻿#region Copyright © 2008 by Christian Rodemeyer
// $HeadURL: http://rodemeyer.googlecode.com/svn/trunk/Rodemeyer/Collections/DefaultDictionary.cs $
// $Revision: 26 $
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace Rodemeyer.Collections
{
    /// <summary>
    /// A Map behaves like a Dictionary with one exception: If you try to get a value for a non existing key
    /// via the indexer, a new value instance is returned instead of an exception.
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class DefaultValueDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        TValue default_value;
        DefaultProviderDelegate default_provider;

        public DefaultValueDictionary()
        {
            default_provider = DefaultDefaultProvider;
        }

        public DefaultValueDictionary(TValue the_default_value)
        {
            default_value = the_default_value;
            default_provider = DefaultDefaultProvider;
        }

        public delegate TValue DefaultProviderDelegate(TKey key);

        public DefaultValueDictionary(DefaultProviderDelegate provider)
        {
            default_provider = provider;
        }

        TValue DefaultDefaultProvider(TKey key)
        {
            return default_value;
        }

        public new TValue this[TKey key]
        {
            get
            {
                TValue v;
                if (!TryGetValue(key, out v))
                {
                    v = default_provider(key);
                    Add(key, v);
                }
                return v;
            }

            set
            {
                base[key] = value;
            }
        }

    }

    public class DefaultDictionary<TKey, TValue>: DefaultValueDictionary<TKey, TValue> where TValue: new()
    {
        public DefaultDictionary(): 
            base (delegate{return new TValue();})
        {
        }
    }
}
